/*
 * cm_mib.h
 *
 *  Created on: 2014年9月23日
 *      Author: chens
 */

#ifndef CM_MIB_H_
#define CM_MIB_H_

#include "cm_mib_id.h"
#include <cm/struct/cm_stack.h>

#define MIB_ALLOC_SIZE (128)

struct cmmib_node {
	cmmib_id id;
	unsigned len;
	char brief[MIB_ALLOC_SIZE];
	union {
		char c;
		short si;
		int i;
		char bytes[MIB_ALLOC_SIZE];
	} data;
	char *dptr;
	struct cmmib_node *next; /* point to brothers, a list */
	struct cmmib_node *children; /* point to children */
};

/*
 * @brief	创建一个新的节点对象
 * @param	id: 节点的ID编号
 * @param	brief: 节点的描述字符串
 * @param	data: 节点中的数据
 * @param	len: 数据的长度
 * @return	成功返回一个非空的节点对象,失败返回NULL
 */
struct cmmib_node * cmmib_newnode(cmmib_id id, const char *brief,
		const void *data, unsigned len);

/*
 * @brief	删除并释放一个节点的空间
 */
void cmmib_delnode(struct cmmib_node **node);

/*
 * @brief	在root中遍历寻找ID等于 id 的节点
 */
struct cmmib_node * cmmib_find(cmmib_id id, struct cmmib_node *root);

/*
 * @brief	将node节点插入根为root的树中，前提: node必须是root的孩子或者后代 TODO
 */
int cmmib_insert(struct cmmib_node *node, struct cmmib_node *root);

/*
 * @brief	将以root为根的树保存到文件中,filename指明文件全路径名
 */
int save_tree(struct cmmib_node *root, const char *filename);

/*
 * @brief	从文件中加载一颗mib树
 */
int load_tree(struct cmmib_node * root, const char *filename);

typedef void (*mib_node_func)(struct cmmib_node *node, void *arg);

/*
 * @brief	以非递归方式中序遍历节点
 * @param	root: 遍历开始的节点
 */
static inline void for_each_node(struct cmmib_node *root, mib_node_func func,
		void *arg)
{
	struct cm_stack *stack = cm_stack_create(sizeof(struct cmmib_node *),
	CMMIB_MAX_LEVEL);
	if (stack == NULL) {
		printf("create stack failed.\n");
		return;
	}
	struct cmmib_node *tmp = root;
	while (tmp != NULL || !cm_stack_empty(stack)) {
		if (tmp != NULL && tmp == root->next)
			break;/* 引入tmp是为了防止遍历root的兄弟，只遍历孩子和他自己 */
		while (tmp != NULL) {
			func(tmp, arg);
			cm_stack_push(stack, (char*) &tmp);
			tmp = tmp->children;
		}

		if (!cm_stack_empty(stack)) {
			cm_stack_pop(stack, (char *) &tmp);
			tmp = tmp->next;
		}
	}
	cm_stack_delete(&stack);
}

#endif /* CM_MIB_H_ */
